Skip to content

chore(repo): migrate to material_ui and cupertino_ui - #2896

Draft
xsahil03x wants to merge 6 commits into
masterfrom
chore/migrate-material-cupertino-ui
Draft

chore(repo): migrate to material_ui and cupertino_ui#2896
xsahil03x wants to merge 6 commits into
masterfrom
chore/migrate-material-cupertino-ui

Conversation

@xsahil03x

@xsahil03x xsahil03x commented Aug 14, 2026

Copy link
Copy Markdown
Member

Submit a pull request

Linear: FLU-696

CLA

  • I have signed the Stream CLA (required).
  • The code changes follow best practices
  • Code changes are tested (add some information if not applicable)

Description of the pull request

⚠️ Stacked on #2894 — review/merge that first. Base this diff against chore/flutter-3.44.0, not master.

🛑 BLOCKED — not mergeable as-is. 19 type errors remain, and every one of them is upstream. See Why it's blocked.

Flutter has split Material and Cupertino out of the framework into the flutter.dev-published material_ui and cupertino_ui packages — both v1.0.0, published 2026-08-12, the same day as Flutter 3.47 stable.

Both require flutter: >=3.44.0. That is exactly the floor #2894 raises, which is what makes this work possible now and why it is stacked rather than standalone.

What changed

  • 409 import directives across 405 tracked files. package:flutter/material.dartpackage:material_ui/material_ui.dart (403) and package:flutter/cupertino.dartpackage:cupertino_ui/cupertino_ui.dart (6). Only the URI is replaced, so the three imports carrying show/hide clauses keep them. Verified up front that every occurrence is a plain import directive — there are no export directives and no doc/string references to either URI anywhere in the repo.
  • Dependencies added to the 10 pubspecs that need them (material_ui ×10, cupertino_ui ×4), and both registered in melos.yaml's command.bootstrap.dependencies — the workspace's single version registry, where every shared dependency is pinned.
  • directives_ordering reapplied via dart fix (188 files). Renaming the URIs moved them relative to their neighbours; the lint is enabled repo-wide, so this is a consequence of the rewrite, not unrelated churn.
  • Localizations (step 2 of the official guide). GlobalMaterialLocalizations now comes from material_ui and GlobalCupertinoLocalizations from cupertino_ui; GlobalWidgetsLocalizations stays in flutter_localizations, which is still its home. The flutter_localizations import is narrowed with a show so its own GlobalMaterialLocalizations can't collide with material_ui's. The public barrel re-exports each from its new home — this is a public API change for stream_chat_localizations.

Why the migration is hand-rolled, not dart fix

The README says to run dart fix --apply --code=migrate_design_widgets. That does not work in Flutter 3.47. The transform ships in the SDK at fix_data/fix_material/fix_material.yaml, but it is a data-driven replacedBy keyed off the library being deprecated — and package:flutter/material.dart carries no @Deprecated annotation in 3.47. The transform's own comment reads TODO(Piinks): Link eventual deprecation PR. Against the real packages dart fix reports Nothing to fix! even with the lint enabled and the diagnostic firing 13×.

The rewrite reproduces that fix's output byte-for-byte, confirmed against a probe package where the fix does apply.

Why it's blocked

material_ui ships its own implementations, and Flutter 3.47's material.dart does not re-export them. So flutter/material's ThemeData / ThemeExtension / ColorScheme and material_ui's are unrelated types. Reproduced minimally:

error - The argument type 'ThemeData (where ThemeData is defined in .../flutter/lib/src/material/theme_data.dart)'
        can't be assigned to the parameter type 'ThemeData (where ThemeData is defined in .../material_ui-1.0.0/lib/src/theme_data.dart)'

The 19 remaining errors are all that collision, from two dependencies that haven't migrated:

Source Errors Cause
stream_core_flutter 18 StreamTheme extends ThemeExtension<StreamTheme> still binds Flutter's ThemeExtension
dynamic_color 1 DynamicColorBuilder's builder takes Flutter's ColorScheme

stream_core_flutter must migrate first — it's ours, so that's a sequencing decision, not a wait. dynamic_color is third-party and only affects sample_app.

MaterialUiCompatibilityBridge does not rescue this. It is documented as an app-level tool for a modern app hosting legacy widgets; it bridges ThemeData/MaterialLocalizations at runtime and does nothing for compile-time signature mismatches, nor for the reverse case of a legacy app hosting a migrated SDK.

Consumer impact

For the same reason, this is breaking for every consumer of stream_chat_flutter: once our public API speaks material_ui types, an app still on package:flutter/material.dart gets the error above, and Theme.of(context) lookups won't resolve across the two universes at runtime. This needs a major version and coordination with the other Stream SDKs.

Testing

Check Result
dart analyze --fatal-infos @ 3.44.0 floor 19 errors, all upstream (table above); 0 otherwise
dart format, 1004 tracked files 0 changed
stream_chat_flutter_core 362 passed
stream_chat_persistence 302 passed
stream_chat_localizations 3 failed — same upstream blocker, via stream_chat.dart:209
stream_chat_flutter not runnable — blocked at compile

Goldens were not run or regenerated: the package doesn't compile until the blocker clears, and material_ui's widgets may rasterise differently, so the ~40-golden macOS baseline from #2894 needs re-checking once it does.

Follow-up

migrate_design_widgets is enabled in analysis_options.yaml, as the regression guard for this migration — without it a new package:flutter/material.dart import would pass CI and silently reintroduce the split.

This is safe at the 3.44 floor even though that analyzer doesn't recognise the rule. undefined_lint is reported against analysis_options.yaml itself, so it only surfaces when that file is inside the analysed directory. legacy_version_analyze runs cd packages/X/lib && dart analyze --fatal-infos ., which leaves the options file out of scope — verified exit 0 from lib/ versus exit 2 from the package root with the same unknown rule enabled. The main analyze job runs the latest stable, which knows the rule. It fires 0 times across all seven packages now that the migration is complete.

Screenshots / Videos

Not applicable — no intended visual change. Any pixel movement from material_ui's implementations is a finding, not an expectation.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 75b93240-fbbb-4715-9085-0fb2bcad885b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@xsahil03x
xsahil03x force-pushed the chore/flutter-3.44.0 branch from b132c80 to 1a398e3 Compare August 17, 2026 09:08
xsahil03x and others added 2 commits August 17, 2026 11:19
Per the SDK's "minimum supported = latest stable - 1" policy, Flutter
3.47.0 shipping on 2026-08-12 makes 3.44.0 (Dart 3.12.0) the new floor.
Following #2721/#2108/#2068, a floor raise is not marked breaking:
existing code keeps compiling, older SDKs simply stop resolving the new
version, and the CHANGELOG bullet goes under Changed rather than
Breaking.

Moves the three version knobs that must stay in lockstep — melos.yaml
(source of truth), .fvmrc, and legacy_version_analyze.yml's
flutter_version — plus the 13 pubspecs melos propagates to.

Raising the Dart constraint also raises each package's language version,
which activated `prefer_initializing_formals` on previously-silent
sites: Dart 3.12 legalised `this._privateField` as a named parameter, so
the lint's suggested fix only became expressible now. Applied via
`dart fix --apply --code=prefer_initializing_formals`, verified by hand:

- No doc comment was rewritten or dropped by the refactor.
- Every introduced `this._foo` replaced a parameter named exactly `foo`,
  so no public call site changes. Assignments whose names differ or
  carry a default (`_provider = tokenProvider`, `_locationProvider =
  locationProvider ?? LocationProvider()`) were correctly left alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rebase onto v10.3.0 renamed each CHANGELOG's 'Upcoming' heading to
'10.3.0', which silently moved the floor-raise bullets into an
already-released section. Git reported no conflict, because the release
edited line 1 while the bullets sit ~35 lines down.

Adds a fresh Upcoming section above 10.3.0 in all five packages and moves
the bullets into it. stream_chat keeps its 10.3.0 'Changed' section,
since the release's own dio bullet still lives there; the other four had
sections containing only the floor-raise bullet, so those are removed
rather than left empty.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xsahil03x
xsahil03x force-pushed the chore/flutter-3.44.0 branch from c1edd96 to d0478f3 Compare August 17, 2026 09:19
xsahil03x and others added 3 commits August 17, 2026 11:21
Flutter split Material and Cupertino out of the framework into the
flutter.dev-published `material_ui` / `cupertino_ui` packages (both
v1.0.0, 2026-08-12, the same day as Flutter 3.47 stable). Both require
`flutter: >=3.44.0`, which is exactly the floor raised in the parent
commit — that is what unblocks this work, and why it is stacked.

Rewrites all 409 import directives across 405 tracked files:
`package:flutter/material.dart` -> `package:material_ui/material_ui.dart`
(403) and `package:flutter/cupertino.dart` ->
`package:cupertino_ui/cupertino_ui.dart` (6). Only the URI is replaced,
so the three imports carrying `show`/`hide` clauses keep them. Every
occurrence was verified to be a plain import directive first: no export
directives and no doc/string references to either URI exist in the repo.

The migration is done by hand rather than by the README's
`dart fix --apply --code=migrate_design_widgets`. That fix is staged in
the SDK's `fix_data/fix_material/fix_material.yaml` but inert here: it is
a data-driven `replacedBy` keyed off the library being deprecated, and
`package:flutter/material.dart` carries no `@Deprecated` annotation in
3.47 yet (the transform's own TODO reads "Link eventual deprecation
PR"). `dart fix` reports "Nothing to fix!" against the real packages.
The rewrite reproduces that fix's output exactly, confirmed against a
probe package where it does apply.

Reordering the imports moved them relative to their neighbours, so
`directives_ordering` is reapplied via `dart fix` (188 files).

Localizations follow step 2 of the migration guide:
`GlobalMaterialLocalizations` now comes from `material_ui` and
`GlobalCupertinoLocalizations` from `cupertino_ui`, while
`GlobalWidgetsLocalizations` stays in `flutter_localizations`, which is
still its home. The `flutter_localizations` import is narrowed with a
`show` so its own `GlobalMaterialLocalizations` cannot collide with
material_ui's. The public barrel re-exports each from its new home.

BLOCKED, and not mergeable as-is: 19 type errors remain, all of them the
two type universes failing to meet. `material_ui` ships its own
implementations and Flutter 3.47's `material.dart` does not re-export
them, so `flutter/material`'s `ThemeData`/`ThemeExtension`/`ColorScheme`
are unrelated types to `material_ui`'s. 18 come from
`stream_core_flutter`, whose `StreamTheme extends
ThemeExtension<StreamTheme>` still binds Flutter's `ThemeExtension`; 1
from `dynamic_color`, whose `DynamicColorBuilder` takes Flutter's
`ColorScheme`. Both dependencies must migrate before this can land.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`command.bootstrap.dependencies` is the workspace's single version
registry — every shared dependency is pinned there, not only in the
pubspecs that use it. The previous commit added both packages to the 14
pubspec entries but skipped the registry, leaving their versions
unmanaged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Without the lint nothing stops a new file importing
package:flutter/material.dart, silently reintroducing the split between
Flutter's Material types and material_ui's.

Enabling it is safe at the 3.44 floor even though that analyzer does not
recognise the rule. `undefined_lint` is reported against
analysis_options.yaml itself, so it only surfaces when that file is
inside the analysed directory. legacy_version_analyze runs
`cd packages/X/lib && dart analyze --fatal-infos .`, which leaves the
options file out of scope: verified exit 0 from lib/ versus exit 2 from
the package root with the same unknown rule enabled. The main analyze
job runs the latest stable, which knows the rule.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xsahil03x
xsahil03x force-pushed the chore/migrate-material-cupertino-ui branch from 6bfff32 to 87079f4 Compare August 17, 2026 09:22
@xsahil03x
xsahil03x marked this pull request as ready for review August 17, 2026 09:25
The migration commit dropped `jni` from the linux and windows
`generated_plugins.cmake` of the stream_chat_flutter example. That was
never intended: it came from a local `melos bootstrap` writing the files
and a `git add -A` sweeping them in.

CI's bootstrap regenerates them *with* `jni`, so the committed files came
back modified and `validate-formatting.sh` — which fails on any
`git ls-files --modified` after bootstrap — reported them under "These
files are not formatted correctly". Restoring master's version makes the
format job clean again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@xsahil03x
xsahil03x marked this pull request as draft August 17, 2026 12:18
Base automatically changed from chore/flutter-3.44.0 to master August 17, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant